package com.github.gaojh.ioc.bean;

import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.github.gaojh.config.Environment;
import com.github.gaojh.ioc.IocUtil;
import com.github.gaojh.ioc.annotation.Autowired;
import com.github.gaojh.ioc.annotation.Value;
import com.github.gaojh.server.utils.JsonTools;
import lombok.extern.slf4j.Slf4j;
import net.sf.cglib.beans.BeanGenerator;
import net.sf.cglib.beans.BulkBean;

import java.lang.reflect.Field;
import java.util.List;

/**
 * @author gaojh
 * @since 2020/3/29
 */
@Slf4j
public class InjectionInitializer implements Initializer {

    private ClassScanner classScanner;

    @Override
    public void init(ClassScanner classScanner) throws Exception {
        this.classScanner = classScanner;

        List<ClassInfo> list = classScanner.getAllClass();
        for (ClassInfo classInfo : list) {
            Object object = IocUtil.getBean(classInfo.getBeanName());
            setFields(object, classInfo.getBeanClass());
        }
    }


    /**
     * 设置Bean的Field
     */
    private void setFields(Object object, Class<?> clazz) throws Exception {
        for (Field field : clazz.getDeclaredFields()) {
            if (field.isAnnotationPresent(Autowired.class)) {
                setAutowiredField(object, ReflectUtil.getField(object.getClass(), field.getName()));
            } else if (field.isAnnotationPresent(Value.class)) {
                setValueField(object, ReflectUtil.getField(object.getClass(), field.getName()));
            }
        }
    }

    private void setAutowiredField(Object object, Field field) throws Exception {
        String fieldName = classScanner.getBeanName(field.getType());
        Object fieldObject = IocUtil.getBean(fieldName);
        ReflectUtil.setFieldValue(object, field, fieldObject);
    }

    private void setValueField(Object object, Field field) {
        Value value = field.getAnnotation(Value.class);
        String valueStr = value.value();
        if (StrUtil.isBlank(valueStr)) {
            throw new RuntimeException(String.format("[%s]中的Field：%s无法设值！", object.getClass().getName(), field.getName()));
        } else if (!StrUtil.containsAny(valueStr, "${", "}")) {
            throw new RuntimeException(String.format("[%s]中的Field：%s表达式格式不正确！", object.getClass().getName(), field.getName()));
        } else {
            String key = StrUtil.subBetween(valueStr, "${", "}");
            ReflectUtil.setFieldValue(object, field, Environment.me.get(key,null));
        }
    }
}
